/*
 * PhotonRTOS础光实时操作系统 -- 中断头文件
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H

#ifdef __KERNEL__

#include <asm/types.h>

/**
 * CPU中断处理
 *	1、获取状态寄存器，并关闭中断
 *	2、打开中断
 *	3、关闭中断
 */

/*
 * CPU interrupt mask handling.
 */
#ifdef CONFIG_CPU_CORTEX_M
#define IRQMASK_REG_NAME_R "primask"
#define IRQMASK_REG_NAME_W "primask"
#define IRQMASK_I_BIT	1
#endif

#ifdef CONFIG_CPU_CORTEX_R
#define IRQMASK_REG_NAME_R "cpsr"
#define IRQMASK_REG_NAME_W "cpsr_c"
#define IRQMASK_I_BIT	(uintptr_t)0x00000080U
#endif

#define ASM_ARCH_LOCAL_IRQ_SAVE									\
	asm volatile(										\
		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ arch_local_irq_save\n"	\
		"	cpsid	i"								\
		: "=r" (flags) : : "memory", "cc");						\

#define ASM_ARCH_LOCAL_SAVE_FLAGS								\
	asm volatile(										\
		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ local_save_flags"		\
		: "=r" (flags) : : "memory", "cc");						\

#define ARCH_FUN_arch_local_irq_save_DEFINED
static inline uintptr_t arch_local_irq_save(void)
{
	uintptr_t flags;

	ASM_ARCH_LOCAL_IRQ_SAVE;

	return flags;
}

#define ARCH_FUN_arch_local_irq_enable_DEFINED
static inline void arch_local_irq_enable(void)
{
	asm volatile(
		"	cpsie i			@ arch_local_irq_enable"
		:
		:
		: "memory", "cc");
}

#define ARCH_FUN_arch_local_irq_disable_DEFINED
static inline void arch_local_irq_disable(void)
{
	asm volatile(
		"	cpsid i			@ arch_local_irq_disable"
		:
		:
		: "memory", "cc");
}

/*
 * 保存恢复中断寄存器
 */
#define ARCH_FUN_arch_local_save_flags_DEFINED
static inline uintptr_t arch_local_save_flags(void)
{
	uintptr_t flags;

	ASM_ARCH_LOCAL_SAVE_FLAGS;

	return flags;
}

#define ARCH_FUN_arch_local_irq_restore_DEFINED
static inline void arch_local_irq_restore(uintptr_t flags)
{
	asm volatile(
		"	msr	" IRQMASK_REG_NAME_W ", %0	@ local_irq_restore"
		:
		: "r" (flags)
		: "memory", "cc");

}

#define ARCH_FUN_arch_irqs_disabled_flags_DEFINED
static inline uintptr_t arch_irqs_disabled_flags(uintptr_t flags)
{
	return flags & IRQMASK_I_BIT;
}

extern bool cat_2_interrupt;
#define ARCH_FUN_arch_local_isr_save_DEFINED
static inline uintptr_t arch_local_isr_save(void)
{
	uintptr_t flags;
	flags = (uintptr_t)cat_2_interrupt;
	cat_2_interrupt = false;
	return flags;
}

#define ARCH_FUN_arch_local_isr_restore_DEFINED
static inline void arch_local_isr_restore(uintptr_t flags)
{
	cat_2_interrupt = (bool)flags;
}
#endif

#endif


